#include<sys/epoll.h>

#include "Channel.h"
#include "Logger.h"
#include "EventLoop.h"

const int Channel::kNoneEvent=0;
const int Channel::kReadEvent=EPOLLIN | EPOLLPRI;
const int Channel::kWriteEvent=EPOLLOUT;


Channel::Channel(EventLoop* loop,int fd)
    :loop_(loop), fd_(fd), events_(0), revents_(0), index_(-1), tied_(false) {}

Channel::~Channel() {}

// 什么时候调用？
void Channel::tie(const std::shared_ptr<void>& obj)
{
    tie_=obj;
    tied_=true;
}

// 当改变channel所表示的fd的evevts事件后 update负责在epoller内更改fd相应事件的epoll_ctl
void Channel::update()
{
    // 通过channel所属的EventLoop 调用poller相应的方法 注册fd的events事件
    loop_->updateChannel(this);
}

// 在channel所属的EventLoop中 把当前channel删除掉
void Channel::remove()
{
    loop_->removeChannel(this);
}

void Channel::handleEvent(Timestamp recvTime)
{
    if(tied_)
    {
        // 升级为强引用
        std::shared_ptr<void> guard =tie_.lock();
        if(guard)
        {
            handleEventWithGuard(recvTime);
        }
    }
    else
    {
        handleEventWithGuard(recvTime);
    }

}

// 根据poller通知的channel发生的具体事件 由channel负责调用具体的回调事件
/*
    检查这个回调是否已经绑定了具体的处理逻辑
    std::function 重载了 operator bool()
    当它绑定了实际的可调用对象时返回 true 如果未绑定任何逻辑则返回 false
*/
void Channel::handleEventWithGuard(Timestamp recvTime)
{
    LOG_INFO("channel handelEvent revents:%d",revents_);
    if((revents_&EPOLLHUP)&&!(revents_&EPOLLIN))
    {
        if(closeCallback_)
        {
            closeCallback_();
        }
    }
    if(revents_&EPOLLERR)
    {
        if(errorCallback_)
        {
            errorCallback_();
        }
    }
    if(revents_&(EPOLLIN | EPOLLPRI))
    {
        if(readCallback_)
        {
            readCallback_(recvTime);
        }
    }
    if(revents_&EPOLLOUT)
    {
        if(writeCallback_)
        {
            writeCallback_();
        }
    }
}